package com.meituan.catering.management.common.api.factory;

import com.meituan.catering.management.common.model.api.Status;
import com.meituan.catering.management.common.model.enumeration.IError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * @author mac
 */
public class ResponseFactory {
    private final static Logger LOGGER = LoggerFactory.getLogger(ResponseFactory.class);

    private ResponseFactory() {
    }

    /**
     * 构造一个成功的结果对象
     *
     * @param data  接口响应数据结果
     * @param clazz 接口响应模型的类型
     * @param <T1>  接口响应数据结果
     * @param <T2>  接口响应模型的类型
     * @return 响应结果
     */
    public static <T1, T2> T2 success(T1 data, Class<T2> clazz) {
        Method setData = MethodCacheManager.fetchMethod(clazz, "setData");
        Method setStatus = MethodCacheManager.fetchMethod(clazz, "setStatus");

        T2 obj = null;
        try {
            obj = clazz.newInstance();
            Class<?> paramClazz = setStatus.getParameterTypes()[0];
            if (Status.class.equals(paramClazz)) {
                setStatus.invoke(obj, new Status());
            } else {
                setStatus.invoke(obj, new Status());
            }
            setData.invoke(obj, data);
        } catch (Exception e) {
            LOGGER.error("error:", e);
        }

        return obj;
    }

    public static <T> T fail(IError error, Class<T> clazz) {
        return fail(error.getCode(), error.getMessage(), clazz);
    }

    /**
     * 使用指定的errorCode、errorMsg、failureInfo构造返回一个失败的结果对象.
     *
     * @param errorCode 错误码
     * @param errorMsg  错误描述
     * @param clazz     接口响应结果类型
     * @param <T>       接口响应结果类型
     * @return 接口响应结果
     */
    private static <T> T fail(Integer errorCode, String errorMsg, Class<T> clazz) {
        Method setStatus = MethodCacheManager.fetchMethod(clazz, "setStatus");

        T obj = null;
        try {
            obj = clazz.newInstance();
            Class<?> paramClazz = setStatus.getParameterTypes()[0];
            if (Status.class.equals(paramClazz)) {
                Status status = new Status();
                status.setCode(errorCode);
                status.setMsg(errorMsg);
                setStatus.invoke(obj, status);
            } else {
                setStatus.invoke(obj, new Status(errorCode, errorMsg));
            }
        } catch (Exception e) {
            LOGGER.error("error:", e);
        }

        return obj;
    }

}
